import os.path
from copy import copy

import pygame

import parse
import maps
import waves
import units
import turrets
import buildings
import collision
import paths
from vectors import Vector

class Stage(object):
	def __init__(self, entries, path):
		self.waves = set()
		
		def parse_waves(lines):
			def wave(entry_node, timings, *units):
				self.waves.add(waves.Wave(entry_node, timings, units))
			
			globals = {"unit": units.Infantry, "fast": units.Commando, "None": -1, "tank": units.Tank}
			globals.update(entries)
			
			parse.section(lines, {"wave": wave}, globals=globals)
		
		parsers = {
			"waves": parse_waves}
		
		parser = parse.Parser(file=open(path), parsers=parsers)
		parser.section("waves")

class Level(object):
	def __init__(self, game, campaign, path):
		self.campaign = campaign
		self.tracks = None
		
		self.levelname = os.path.split(path)[1]
		filepath = os.path.join(path, "%s.level.txt" % self.levelname)
		levelfile = open(filepath)
		
		details = {}
		object_names = {}
		
		def parse_objects(lines):
			class Objects(dict):
				def __getitem__(self, key):
					object_type = super(Objects, self).__getitem__(key)
					
					def object(*args):
						object = object_type(game, *args)
						
						if object is not None:
							game.objects.add(object)
						
						return object
						
					return object
			
			def criticals(level, object):
				game.criticals.add(object)
			
			def socket(*args, **kwargs):
				socket = turrets.Socket(*args, **kwargs)
				game.sockets.add(socket)
				return socket
			
			object_types = Objects({
				"turret socket": socket,
				"mouse turret": turrets.MouseTurret,
				"auto turret": turrets.AutoTurret,
				"button turret": turrets.ButtonTurret,
				"command center": buildings.Command,
				"defend": criticals})
			
			object_names.update(parse.section(lines, object_types, globals={"auto": True}))
		
		def parse_paths(lines):
			def link(a, b):
				a[-1].link(b[0])
			
			def entry(path, name):
				game.entries[name] = path[0]
			
			object_types = {
				"path": paths.Move.path,
				"attack node": paths.Attack.path,
				"end node": paths.End.path,
				"entry point": entry}
			
			parse.section(lines, object_types, object_names, operators={"->": link})
		
		parsers = {
			"details": parse.details(details),
			"objects": parse_objects,
			"paths": parse_paths}
		
		parser = parse.Parser(file=levelfile, path=path, parsers=parsers)
		
		parser.section("details")
		parser.section("objects")
		parser.section("paths")
		
		self.name = details["name"]
		self.author = details["author"]
		self.map = os.path.join(path, "%s.map.txt" % details["map"])
		
		def stage(name):
			stagepath = os.path.join(path, "%s.stage.txt" % name)
			return Stage(game.entries, stagepath)
		
		self.stages = iter(stage(name) for name in details["stages"])
		self.stage = self.stages.next()
		
		self.graph = waves.Graph(self.stage.waves)	
	def update(self, frame):		
		"""if self.graph.end > 0 and frame >= self.graph.end:
			self.stage = self.stages.next()
			self.graph = waves.Graph(self.stage.waves)"""
		pass

